home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 111_01 / bcanlyz.c < prev    next >
Text File  |  1985-08-19  |  10KB  |  600 lines

  1. /*
  2. HEADER:        ;
  3. TITLE:        Expression evaluator;
  4. VERSION:    1.0;
  5.  
  6. DESCRIPTION:    "Auxiliary file for BC.C.  May be useful in other C programs.
  7.         Evaluates arithmetic and logic expressions.  Takes a string
  8.         expression as argument, and returns the value of the
  9.         expression, an integer, 0 through 65535.";
  10.  
  11. KEYWORDS:    Arithmetic, logical, expression, evaluator, calculator;
  12. SYSTEM:        CP/M-80;
  13. FILENAME:    BCANLYZ.C;
  14. WARNINGS:    "Limited to integers, 0 to 65535.";
  15. SEE-ALSO:    BC.C, BC.DOC, BCDEF.H, BCREVIEW.DOC;
  16. AUTHORS:    Jan Larsson;
  17. COMPILERS:    BDS C;
  18. */
  19. /*********************************************************************
  20.  
  21. Delimiters: \0, \n, \f, ,, ), ;
  22. Operators: +, -, *, /, <, >, %, &, |, ^, mod, and, or, xor, shl, shr
  23. Unary operators: +, -, ~, not
  24.  
  25.            (c) 1981 Jan Larsson
  26.  
  27. **********************************************************************/
  28.  
  29. #include "bcdef.h"
  30.  
  31. unsigned anlyz( s )
  32. char *s ;
  33. {
  34.     int nesting, *depth ;
  35.     char *p ;
  36.     int n, left, right ;
  37.     unsigned result ;
  38.  
  39.     depth = &nesting ;
  40.     *depth = 0 ;
  41.     p = s ; right = left = 0 ;
  42.     while(*p != EOL){
  43.         if(*p == LPAREN)left++ ;
  44.         if(*p == RPAREN)right++ ;
  45.         p++ ;
  46.         }
  47.     if(right > left)
  48.         printf("%4u: Missing left parenthesis in expression.\n",line());
  49.     else if(right < left)
  50.         printf("%4u: Missing right parenthesis in expression.\n",line());
  51.     else return( anlyz2( s ) );
  52.     return( FALSE );
  53. }
  54.  
  55.  
  56.  
  57.  
  58. /*
  59.       O.k. evaluate a simple expression  <value> <operator> <value> .
  60.       If a parenthesis occurs anlyz2 does a recursive call on itself
  61.       to evaluate it first. No operator precedence is implemented, just
  62.       simple left --> right evaluation. 
  63. */
  64.  
  65. unsigned anlyz2( s, depth )
  66. char *s ;
  67. int *depth ;
  68. {
  69.     char error, op, *skipsp(), *skipexpr() ;
  70.     char *skiptok(), *skipop(), gettop() ;
  71.     char unary, isunary() ;
  72.     unsigned rval, lval, gettok() ;
  73.  
  74.     error = FALSE ;
  75.     *depth++ ;
  76.     s = skipsp( s );
  77.  
  78.     if(eoe(*s)){aerror(0);*depth--;return(0);}
  79.     while(!eoe(*s)){
  80.         unary = isunary( s );
  81.         if(unary != FALSE)s = skipop( s );
  82.         if(*s == LPAREN){ lval = anlyz2( s+1 );
  83. s = skipexpr( s );}
  84.         else { lval = gettok( s ); s = skiptok( s ); }
  85.         if(unary != FALSE){
  86.         switch (unary) {
  87.             case PLUS     : break ;
  88.             case MINUS    : lval = - lval ; break ;
  89.             case NOT      : lval = ~ lval ; break ;
  90.             case SNOT     : lval = ~ lval ; break ;
  91.             }
  92.         unary = FALSE ;
  93.         }
  94.         if(!eoe(*s)){
  95.           for(;;){
  96.         if(eoe(*s)){ aerror( 1 ) ; break ;}
  97.         op = gettop( s ); s = skipop( s );
  98.         if(eoe(*s)){ aerror(2); break ;}
  99.         unary = isunary( s );
  100.         if(unary != FALSE)s = skipop( s );
  101.         if(*s == LPAREN){ rval = anlyz2( s+1 ); s = skipexpr( s );}
  102.         else { rval = gettok( s ); s = skiptok( s );}
  103.         if(unary != FALSE){
  104.             switch (unary) {
  105.             case MINUS   : rval = - rval ; break ;
  106.             case SNOT    : rval = ~ rval ; break ;
  107.             case PLUS     : break ;
  108.             case NOT      : rval = ~ rval ; break ;
  109.             }
  110.             unary = FALSE ;
  111.             }
  112.         lval = calc( lval, op, rval );
  113.         if(eoe(*s))break;
  114.         }
  115.         }
  116.     }
  117.     *depth-- ;
  118.     return( lval );
  119. }
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126. /*
  127.     Return true if c is an end_of_expression delmiter, else false
  128. */
  129.  
  130. eoe( c )
  131. char c ;
  132. {
  133.     switch (c) {
  134.         case NEWLINE   :
  135.         case FORMFEED  :
  136.         case EOL       :
  137.         case RPAREN    :
  138.         case COMMA     :
  139.         case SEMICOLON : return( TRUE );
  140.         default        : return( FALSE );
  141.     }
  142. }
  143.  
  144.  
  145.  
  146. /*
  147.     Return TRUE if c is a space character (to be ignored), else FALSE
  148. */
  149.  
  150. spc( c )
  151. char c ;
  152. {
  153.     switch (c) {
  154.         case SPACE    :
  155.         case COLON    :
  156.         case TAB      :
  157.         case SPACE    : return( TRUE );
  158.         default       : return( FALSE );
  159.         }
  160. }
  161.  
  162.  
  163.  
  164.  
  165. /*
  166.     Return TRUE if c is a legal operator, else FALSE
  167. */
  168.  
  169. op( c )
  170. char c ;
  171. {
  172.     switch (c) {
  173.         case PLUS      :
  174.         case MINUS     :
  175.         case MULT      :
  176.         case DIV       :
  177.         case NOT       :
  178.         case XOR       :
  179.         case AND       :
  180.         case SHL       :
  181.         case SHR       :
  182.         case MOD       :
  183.         case OR        : return( TRUE );
  184.         default        : return( FALSE );
  185.         }
  186. }
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193. /*
  194.       Her we take a pointer as argument, increments it until it
  195.     finds the next non-space character, then return pointer value.
  196. */
  197.  
  198. char *skipsp( s )
  199. char *s ;
  200. {
  201.     while(spc( *s ) && !eoe(*s))s++ ;
  202.     return( s );
  203. }
  204.  
  205.  
  206.  
  207.  
  208. /*
  209.     Skiptok takes a pointer as argument, returns a pointer to the first
  210.     position after the current token (numeric constant, symbol etc.)
  211. */
  212.  
  213. char *skiptok( s )
  214. char *s ;
  215. {
  216.     s = skipsp( s );
  217.     while(!spc( *s ) && !op( *s ) && !eoe( *s ) && *s != LPAREN)s++ ;
  218.     s = skipsp( s );
  219.     return( s );
  220. }
  221.  
  222.  
  223.  
  224. /*
  225.     Skipop takes the pointer argument, skips the current operator
  226.     and returns pointer value.
  227. */
  228.  
  229. char *skipop( s )
  230. char *s ;
  231. {
  232.     s = skipsp( s );
  233.     if(op( *s ))s++ ;
  234.     else s = skiptok( s );
  235.     s = skipsp( s );
  236.     return( s );
  237. }
  238.  
  239.  
  240.  
  241. /*
  242.     Skipexpr increments pointer S to the end of the current simple
  243.     expression, if a nested expresssion turns up, a recursive call
  244.     is made to Skipexpr.
  245. */
  246.  
  247. char *skipexpr( s )
  248. char *s ;
  249. {
  250.     if(*s == LPAREN)s++ ;
  251.     while(!eoe( *s )){
  252.         if(*s == LPAREN)s = skipexpr( s );
  253.         else s++ ;
  254.         }
  255.     if(*s == RPAREN)s++ ;
  256.     s = skipsp( s );
  257.     return( s );
  258. }
  259.  
  260.  
  261.  
  262. /*
  263.     This procedures calculates a simple expression and returns the 
  264.     value.
  265. */
  266.  
  267. unsigned calc( val1, op, val2 )
  268. unsigned val1, val2 ;
  269. char op ;
  270. {
  271.     switch (op) {
  272.         case PLUS      : return( val1 + val2 );
  273.         case MINUS     : return( val1 - val2 );
  274.         case MULT      : return( val1 * val2 );
  275.         case DIV       : return( val1 / val2 );
  276.         case OR        : return( val1 | val2 );
  277.         case AND       : return( val1 & val2 );
  278.         case XOR       : return( val1 ^ val2 );
  279.         case MOD       : return( val1 % val2 );
  280.         case SHL       : return( val1 << val2 );
  281.         case SHR       : return( val1 >> val2 );
  282.         default        : aerror(3);return( 0 );
  283.         }
  284. }
  285.  
  286.  
  287.  
  288.  
  289.  
  290. /*
  291.     Here we return a single byte representation of the current operator,
  292.     this is used in the switch statement in CALC.
  293. */
  294.  
  295. char gettop( s )
  296. char *s ;
  297. {
  298.     char operator[80] ;
  299.  
  300.     s = skipsp( s );
  301.     if(op( *s ))return( *s );
  302.     else {
  303.         token( s, operator );
  304.         if(strcmp( operator, TXAND ) == 0)return( AND );
  305.         if(strcmp( operator, TXXOR ) == 0)return( XOR );
  306.         if(strcmp( operator, TXSHL ) == 0)return( SHL );
  307.         if(strcmp( operator, TXSHR ) == 0)return( SHR );
  308.         if(strcmp( operator, TXMOD ) == 0)return( MOD );
  309.         if(strcmp( operator, TXOR  ) == 0)return( OR  );
  310.          }
  311.     aerror(4);
  312.     return( FALSE );
  313. }
  314.  
  315.  
  316.  
  317.  
  318. /*
  319.     Copy next token from line S to buffer TO
  320. */
  321.  
  322. token( s, to )
  323. char *s, *to ;
  324. {
  325.     char *p, c ;
  326.  
  327.     s = skipsp( s );
  328.     p = s ; s++ ;
  329.     while(!spc( *s ) && !op( *s ) && !eoe( *s ) && *s != LPAREN)s++ ;
  330.     c = *s ; *s = EOL ; 
  331.     strcpy( to, p );
  332.     *s = c ;
  333. }
  334.  
  335.  
  336.  
  337.  
  338. pack( s )
  339. char *s ;
  340. {
  341.     char c, *p ;
  342.  
  343.     for( c = 0 ; c < 7 ; c++ ){
  344.         if(*s == EOL)break ;
  345.         s++ ;
  346.         }
  347.     if(*s++ != EOL){
  348.         p = s ;
  349.         while(*p != EOL)p++ ;
  350.         p-- ; *s++ = *p ;
  351.         *s = EOL ;
  352.         }
  353. }
  354.  
  355.  
  356.  
  357.  
  358. /*
  359.     Return TRUE if next token is a unary operator, else FALSE.
  360. */
  361.  
  362. char isunary( s )
  363. char *s ;
  364. {
  365.     char opr[80] ;
  366.  
  367.     s = skipsp( s );
  368.     switch (*s) {
  369.         case MINUS   :
  370.         case PLUS    :
  371.         case NOT     : return( *s );
  372.         }
  373.     token( s, opr );
  374.     if(strcmp( opr, TXNOT ) == 0)return( SNOT );
  375.     else return( FALSE );
  376. }
  377.  
  378.  
  379.  
  380.  
  381. /*
  382.     Return the binary value of the token at S, this may be a numeric
  383.     constant or a symbol in the symbol table.
  384. */
  385.  
  386. unsigned gettok( s )
  387. char *s ;
  388. {
  389.     char operand[80] ;
  390.  
  391.     s = skipsp( s );
  392.     token( s, operand );
  393.     if(isdigit(operand[0]))return( cbin( operand ) );
  394.     else if(operand[0] == ASCII)return( operand[1] );
  395.     else { pack( operand );
  396.            return( lookup( operand ) );
  397.              }
  398. }
  399.  
  400.  
  401.  
  402. unsigned lookup( s )
  403. char *s ;
  404. {
  405.     return( 0 );
  406. }
  407.  
  408.  
  409.  
  410.  
  411. scp( to, from )
  412.  
  413. char *to, *from ;
  414.  
  415. {
  416.  
  417. char c ;
  418.  
  419. c = *from++ ;
  420. while(c != EOL)
  421. { *to++ = c ;
  422.   c = *from++ ;
  423. }
  424.  
  425. }
  426.  
  427.  
  428. reverse( s )
  429.  
  430. char s[];
  431.  
  432.  
  433. int c, i, j ;
  434.  
  435. for(i = 0, j = strlen( s ) - 1 ; i < j ; i++, j-- )
  436. { c = s[i] ; s[i] = s[j] ; s[j] = c ; }
  437.  
  438. }
  439.  
  440.  
  441. b2asc( c )
  442.  
  443. char c ;
  444.  
  445. {
  446.  
  447. c += '0' ;
  448. if